/**
 * HSV 转 RGB
 *
 * @param {Number} hue - 色相 (0-360)
 * @param {Number} saturation - 饱和度 (0-1)
 * @param {Number} value - 亮度 (0-1)
 * @returns {number[]} RGB 数组，包含 r, g, b 值，取值范围为 0-255
 */
export function hsvToRgbArray(hue, saturation, value) {
  let [r, g, b] = [0, 0, 0];

  if (saturation === 0) {
    r = g = b = value;
  } else {
    const huePrime = hue / 60;
    const chroma = value * saturation;
    const x = chroma * (1 - Math.abs((huePrime % 2) - 1));
    const m = value - chroma;

    const handler = [
      [chroma, x, 0],
      [x, chroma, 0],
      [0, chroma, x],
      [0, x, chroma],
      [x, 0, chroma],
      [chroma, 0, x]
    ];

    const index = Math.floor(huePrime);
    if (index >= 0 && index <= 5) {
      [r, g, b] = handler[index];
    }

    r += m;
    g += m;
    b += m;
  }

  return [r, g, b].map((v) => Math.round(v * 255));
}

/**
 * Hue 转 RGB 数组
 *
 * @param hue hue
 * @returns {(number|number)[]} RGB
 */
export function hueToRgbArray(hue) {
  function computer(val) {
    if (val > 255) {
      return 255;
    } else if (val < 0) {
      return 0;
    }
    return Math.round(val);
  }
  const hueRgb = (hue / 60) * 255;
  const r = computer(Math.abs(hueRgb - 765) - 255);
  const g = computer(510 - Math.abs(hueRgb - 510));
  const b = computer(510 - Math.abs(hueRgb - 1020));
  return [r, g, b];
}

/**
 * 判断是否是hex格式
 * @param {String} hex
 * @returns {boolean}
 */
export function hexValid(hex) {
  return /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(hex);
}

/**
 * Hex 转 Rgb
 *
 * @param {String} hex 十六进制颜色值
 * @returns {String} Rgb
 */
export function hexToRgb(hex) {
  // 判断是否是合法的十六进制颜色值
  if (!hexValid(hex)) {
    return '';
  }

  // 去掉 '#' 前缀
  hex = hex.replace('#', '');

  // 将十六进制颜色字符串拆分为 RGB 组件
  const r = parseInt(hex.slice(0, 2), 16);
  const g = parseInt(hex.slice(2, 4), 16);
  const b = parseInt(hex.slice(4, 6), 16);

  return `rgb(${[r, g, b].join(',')})`;
}

/**
 * hsb 转 hex
 *
 * @param {string} hex color
 * @returns {string} hsb color
 */
export function hexToHsb(hex) {
  // hex -> rgb -> hsb
  return rgbToHsb(hexToRgb(hex));
}

/**
 * hsb 是否有效
 * @param hsb
 * @returns {boolean}
 */
export function hsbValid(hsb) {
  // 使用正则表达式匹配 hsb 格式的字符串
  const hsbPattern = /^hsb\((\d{1,3}),\s*([\d.]+)%,\s*([\d.]+)%\)$/;

  // 测试输入字符串是否符合 hsb 格式
  const match = hsb.match(hsbPattern);
  if (!match) {
    return false;
  }

  // 提取匹配的数值
  const hue = parseFloat(match[1]);
  const saturation = parseFloat(match[2]);
  const brightness = parseFloat(match[3]);

  // 检查 hue 是否在 0 到 360 之间
  if (hue < 0 || hue > 360) {
    return false;
  }

  // 检查 saturation 和 brightness 是否在 0% 到 100% 之间
  return !(saturation < 0 || saturation > 100 || brightness < 0 || brightness > 100);
}

/**
 * hsb 转 hex
 *
 * @param hsb color
 * @returns {string} hex color
 */
export function hsbToHex(hsb) {
  if (!hsbValid(hsb)) {
    return '';
  }

  // 解析 HSB 颜色字符串
  const [, h, s, b] = hsb.match(/(\d+),\s*(\d+)%,\s*(\d+)%/);

  // 将 HSB 转换为 RGB 数组
  const rgbArray = hsvToRgbArray(parseInt(h), parseFloat(s) / 100, parseFloat(b) / 100);

  //将 RGB 数组转换为十六进制颜色字符串
  return `#${rgbArray.map((v) => v.toString(16).padStart(2, '0')).join('')}`;
}

/**
 * hsb 转 rgb
 *
 * @param {String} hsb color
 * @returns {string} rgb color
 */
export function hsbToRgb(hsb) {
  if (!hsbValid(hsb)) {
    return '';
  }

  // 解析 HSB 颜色字符串
  const [, h, s, b] = hsb.match(/(\d+),\s*(\d+)%,\s*(\d+)%/);

  // 将 HSB 转换为 RGB 数组
  const rgbArray = hsvToRgbArray(parseInt(h), parseFloat(s) / 100, parseFloat(b) / 100);

  //将 RGB 数组转换为十六进制颜色字符串
  return `rgb(${rgbArray.join(',')})`;
}

/**
 * rgb 转 hue
 * @param {String} rgb rgb
 * @returns {number|number} hue
 */
export function rgbToHue(rgb) {
  if (!rgbValid(rgb)) {
    throw new Error('Invalid RGB color');
  }
  return rgbArrayToHue(rgbToArray(rgb));
}

/**
 * rgb 转 hsv
 *
 * @param {String} rgb rgb
 * @returns {(number|number|number)[]} hsv
 */
export function rgbToHsv(rgb) {
  if (!rgbValid(rgb)) {
    throw new Error('Invalid RGB color');
  }

  return rgbArrayToHsv(rgbToArray(rgb));
}

/**
 * rgb 转 数组
 * @param {String} rgb
 * @returns {Array<Number>} rgb数组
 */
export function rgbToArray(rgb) {
  // 使用正则表达式提取括号内的数字
  const matches = rgb.match(/\d+/g);
  // 将匹配到的字符串数字转换为整数并返回数组
  return matches ? matches.map(Number) : [];
}

/**
 * rgb 数组是否有效
 *
 * @param {Array<Number>} rgbArray
 * @returns {boolean}
 */
export function rgbArrayValid(rgbArray) {
  if (!Array.isArray(rgbArray) || rgbArray.length !== 3) {
    return false;
  }

  // 判断rgb数组是否合法
  return !rgbArray.some((v) => v < 0 || v > 255);
}

/**
 * rgb 是否有效
 * @param {string} rgb
 * @returns {boolean}
 */
export function rgbValid(rgb) {
  // 判断是否为RGB格式
  const isRgb = /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/.test(rgb);
  if (isRgb) {
    // 获取RGB数值
    const [r, g, b] = rgb
      .replace(/[^\d,]/g, '')
      .split(',')
      .map(Number);

    return r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255;
  }

  return false;
}

/**
 * rgb 数组 转 rgb
 * @param {Array<Number>} rgbArray rgb
 * @returns {string} rgb
 */
export function rgbArrayToRgb(rgbArray) {
  if (!rgbArrayValid(rgbArray)) {
    throw new Error('Invalid RGB color');
  }
  rgbArray = rgbArray.map((v) => Math.round(v));
  return `rgb(${rgbArray.join(',')})`;
}

/**
 * rgb 数组 转 hex
 * @param {Array<Number>} rgbArray rgbArray
 * @returns {string} hex
 */
export function rgbArrayToHex(rgbArray) {
  if (!rgbArrayValid(rgbArray)) {
    throw new Error('Invalid RGB color');
  }
  const hexArray = rgbArray.map((v) => v.toString(16).padStart(2, '0'));
  return `#${hexArray.join('')}`;
}

/**
 * rgb 数组 转 hsv
 * @param {Array<Number>} rgbArray rgbArray
 * @returns {(number|number|number)[]} hsv
 */
export function rgbArrayToHsv(rgbArray) {
  const [r, g, b] = rgbArray;

  const max = Math.max(r, g, b);
  const min = Math.min(r, g, b);
  const delta = max - min;

  const s = max === 0 ? 0 : (delta / max) * 100;
  const v = (max / 255) * 100;

  return [rgbArrayToHue(rgbArray), Math.round(s), Math.round(v)];
}

/**
 * rgb 数组 转 hue
 * @param {Array<Number>} rgbArray
 * @returns {number|number} hue
 */
export function rgbArrayToHue(rgbArray) {
  const [r, g, b] = rgbArray;
  const max = Math.max(r, g, b);
  const min = Math.min(r, g, b);
  const delta = max - min;

  let h;
  if (delta === 0) {
    h = 0;
  } else if (max === r) {
    h = ((g - b) / delta) % 6;
  } else if (max === g) {
    h = (b - r) / delta + 2;
  } else {
    h = (r - g) / delta + 4;
  }

  h = Math.round(h * 60);
  h = h < 0 ? h + 360 : h;

  return h;
}

/**
 * rgb 转 hex
 *
 * @param {string} rgb rgb
 * @returns {string} hex
 */
export function rgbToHex(rgb) {
  // 判断是否是RGB格式
  if (!isRgb(rgb)) {
    return '';
  }

  return rgbArrayToHex(rgbToArray(rgb));
}

/**
 * rgb 转 hsb
 *
 * @param {string} rgb
 * @returns {string} hsb color
 */
export function rgbToHsb(rgb) {
  if (!rgbValid(rgb)) {
    return '';
  }

  return rgbArrayToHsb(rgbToArray(rgb));
}

/**
 * rgb 数组 转 hsb
 *
 * @param {string} rgbArray
 * @returns {string} hsb
 */
export function rgbArrayToHsb(rgbArray) {
  const [r, g, b] = rgbArray;

  const max = Math.max(r, g, b);
  const min = Math.min(r, g, b);
  const delta = max - min;

  const s = max === 0 ? 0 : (delta / max) * 100;
  const v = (max / 255) * 100;

  const h = rgbArrayToHue(rgbArray);

  return `hsb(${h}, ${Math.round(s)}%, ${Math.round(v)}%)`;
}

/**
 * 判断是否是rgb格式
 *
 * @param {String} color
 * @returns {boolean}
 */
export function isRgb(color) {
  return /^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/.test(color);
}

/**
 * 判断是否是颜色
 * @param {String} str
 */
export function isColor(str) {
  return rgbValid(str) || hexValid(str);
}

/**
 * 格式化颜色
 *
 * @param {String} color
 * @returns {*|String}
 */
export function formatRgbColor(color) {
  if (rgbValid(color)) {
    return color;
  }

  return hexToRgb(color) || hsbToRgb(color) || '';
}

/**
 * 格式化颜色 hex
 * @param color
 * @returns {*|string}
 */
export function formatHexColor(color) {
  let value = '';
  if (hexValid(color)) {
    value = color;
  } else {
    value = rgbToHex(color) || hsbToHex(color) || '';
  }
  return value.toUpperCase();
}

/**
 * 格式化颜色 hsb
 *
 * @param color
 */
export function formatHsbColor(color) {
  if (hsbValid(color)) {
    return color;
  }

  return rgbToHsb(color) || hexToHsb(color) || '';
}

/**
 * 格式化颜色
 * @param color
 * @param {String} [format='rgb']
 * @returns {string}
 */
export function formatColor(color, format = 'rgb') {
  let value = '';
  if (color !== void 0 && color !== null && color !== '') {
    if (format === 'rgb') {
      value = formatRgbColor(color);
    } else if (format === 'hex') {
      value = formatHexColor(color);
    } else if (format === 'hsb') {
      value = formatHsbColor(color);
    }
  }

  return value;
}
